package com.apes.fn.scm.retailOrder.service.account.retail;

import com.alibaba.fastjson.JSON;
import com.apes.fn.scm.retailOrder.service.account.BackBatchAndSupplierService;
import com.apes.fn.scm.retailOrder.service.account.RetailAccountData;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.workOrder.model.MaintenanceOrder;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.service.ContractService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.service.BusinessType;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 外协凭证服务 经销带安
 * <p>
 * 外协账目逻辑确认：
 *      如果外协派工时所选的是 “采购合同” ，并且此合同的 公司ID 与 派工门店对应的公司ID不同，
 *      则形成采购合同所属公司对供应商的采购，以及合同所属公司对派工门店公司之间的跨公司销售业务。
 * </p>
 *
 * <p>
 *  小规模纳税人需求地址   https://c3sdlmemys.feishu.cn/wiki/wikcnXWxchvUr8GCyxO39hyinxg?wiki_all_space_view_source=space_sidebar#
 * </p>
 * @Author wuq
 * @Date 2021-7-22
 */
@RetailAccount(value = "outHelp", name = "工单外协凭证")
@Service
public class OutHelpVoucherService extends BackBatchAndSupplierService {

    @Autowired
    private TaxService taxService;
    @Autowired
    private ContractService contractService;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;

    public void process(RetailAccountData retailAccountData) {
        List<MaintenanceOrder> maintenanceOrders = retailAccountData.getMaintenanceOrders();

        Map<Contract, List<MaintenanceOrder>> workOrderItems = maintenanceOrders.stream()
                .filter(item -> "distribution".equals(item.getContract().getCooperation().getId()))
                .collect(Collectors.groupingBy(MaintenanceOrder::getContract));
        if (workOrderItems.isEmpty()) return;

        workOrderItems.forEach((contract, items) -> {
            // 判断合同公司与工单上面的公司是否一致
            if ("supplier".equals(contract.getContractType().getCode()) && !Objects.equals(contract.getCompany().getId(), items.get(0).getCompany().getId())) {
                // 找合同上面的所属公司做采购
                createOutCrossPurchaseVoucher(items);
            } else {
                // 直接找供应商做采购
                createOutPurchaseVoucher(items, false);
            }
        });
    }

    private void createOutPurchaseVoucher(List<MaintenanceOrder> maintenanceOrders, boolean isCross) {
        MaintenanceOrder order = maintenanceOrders.get(0);  // 获取第一个外协工单
        String platformId = order.getPlatform().getId();    // 平台公司

        Voucher purVoucher = new Voucher();
        purVoucher.setBusinessType(BusinessType.PURCHASE_ORDER);
        purVoucher.setClerk(partyRoleRepository.findOne(order.getCreator())); //业务员

        purVoucher.setContract(order.getContract());     // 供应商和平台签署的合同只有一份
        purVoucher.setDept(order.getBelongDept());
        purVoucher.setCompany(order.getCompany());

        if (isCross) {  // 如果是跨公司，就需要找合同上面的公司做采购；非跨公司，就直接找真实供应商采购
            purVoucher.setPartner(purVoucher.getContract().getCompany().getParty().getPatyRoleByType("Supplier"));
        } else {
            purVoucher.setPartner(purVoucher.getContract().getPartner().getParty().getPatyRoleByType("Supplier"));
        }

        purVoucher.setClassification(VoucherType.DISTRIBUTION_INSTALL);
        purVoucher.setCustomerExpand(order.getFnCustomerExpand().getId());

        purVoucher.setOrigin(order.getServicePlanId());
        purVoucher.setOriginBusinessType("ServicePlan");
        purVoucher.setSource(order.getId());
        purVoucher.setSourceBusinessType(order.getBusinessType());

        purVoucher.setInventoryMode(purVoucher.getContract().getCooperation().getInventoryMode());     //设置库存模式：寄售
        purVoucher.setAccountingMethod(purVoucher.getContract().getCooperation().getAccountingMethod());  // 核算方式：采购价

        final PartyRole supplier = purVoucher.getPartner();
        purVoucher.setVoucherItems(
                maintenanceOrders.stream().map(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();
                            voucherItem.setProduct(item.getProduct());
                            voucherItem.setOwner(item.getBelongDept().getCompany());

                            // 设置为销售的单位以及数量
                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(item.getSaleQty());

                            voucherItem.setOriginItemId(item.getServicePlanItem().getId());
                            voucherItem.setSourceItemId(item.getId());

                            Tax tax = taxService.getPurchaseTax(order.getCompany(), supplier, item.getProduct());//供应商进项税
                            voucherItem.setTax(tax);
                            voucherItem.setSupplier(item.getSupplier());
                            voucherItem.setPriceUnit(item.getPlatformPriceCosInTax());  // 采购价格取带安成本单价

                            // 采购价格取带安成本单价
                            if ("1001".equals(platformId)) {
                                voucherItem.setPriceUnit(item.getPriceCostUnitInTax());
                            } else if ("1007".equals(platformId)) {
                                voucherItem.setPriceUnit(item.getPlatformPriceCosInTax());
                            }

                            voucherItem.setInnerSalePriceUnit(item.getPriceCostUnitInTax());    // 公司间交易价
                            return voucherItem;
                        }).collect(Collectors.toSet()));
        if (purVoucher.getVoucherItems().size() == 0) throw new RuntimeException("生成带安采购凭证时报错，没有采购凭证明细！");

        purVoucher = invoke("voucher.create", MapUtil.mapped(purVoucher));
        Map mapped = MapUtil.mapped(purVoucher);

        // 回写方案明细批次以及供应商信息
        sendServicePlanBathAndSupplier(purVoucher);

        //生成账单
        invoke("invoice.create", createInvoiceRequest(mapped,order));
    }

    private void createOutCrossPurchaseVoucher(List<MaintenanceOrder> maintenanceOrders) {
        // 分销单采购以及销售
        Voucher voucher = createCrossPurchaseVoucher(maintenanceOrders);
        createCrossSaleVoucher(voucher, maintenanceOrders);

        // 对合同上面的公司做采购
        createOutPurchaseVoucher(maintenanceOrders, true);
    }


    private Voucher createCrossPurchaseVoucher(List<MaintenanceOrder> maintenanceOrders){
        MaintenanceOrder order = maintenanceOrders.get(0);  // 获取第一个外协工单
        Contract purContract = order.getContract();            // 获取合同

        Voucher purVoucher = new Voucher();
        purVoucher.setBusinessType(BusinessType.PURCHASE_ORDER);
        purVoucher.setClerk(partyRoleRepository.findOne(order.getCreator())); //业务员

        purVoucher.setDept(purContract.getDept());
        purVoucher.setCompany(purContract.getCompany());
        purVoucher.setPartner(purContract.getPartner().getParty().getPartyRoleByType("Supplier"));     // 外部供应商

        Contract contract = contractService.getContract(purVoucher.getDept(), purVoucher.getPartner(), "distribution", "supplier", "零售工单外协业务");
        purVoucher.setContract(contract);
        purVoucher.setCustomerExpand(order.getFnCustomerExpand().getId());

        purVoucher.setOrigin(order.getServicePlanId());
        purVoucher.setOriginBusinessType("ServicePlan");
        purVoucher.setSource(order.getId());
        purVoucher.setSourceBusinessType(MaintenanceOrder.class.getSimpleName());

        purVoucher.setInventoryMode(purVoucher.getContract().getCooperation().getInventoryMode());     // 库存模式
        purVoucher.setAccountingMethod(purVoucher.getContract().getCooperation().getAccountingMethod());  // 核算方

        final PartyRole supplier = purVoucher.getPartner();
        purVoucher.setVoucherItems(
                maintenanceOrders.stream().map(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();
                            voucherItem.setProduct(item.getProduct());

                            // 设置为销售的单位以及数量
                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(item.getSaleQty());

                            voucherItem.setOriginItemId(item.getServicePlanItem().getId());
                            voucherItem.setSourceItemId(item.getId());
                            voucherItem.setOwner(purContract.getCompany());

                            Tax tax = taxService.getPurchaseTax(purContract.getCompany(), supplier, item.getProduct());//供应商进项税
                            voucherItem.setTax(tax);
                            voucherItem.setSupplier(item.getSupplier());
                            voucherItem.setPriceUnit(item.getPlatformPriceCosInTax());  // 采购价格取带安成本单价
                            voucherItem.setInnerSalePriceUnit(item.getPriceCostUnitInTax());    // 公司间交易价
                            return voucherItem;
                        }).collect(Collectors.toSet()));

        if (purVoucher.getVoucherItems().size() == 0) throw new RuntimeException("生成带安采购凭证时报错，没有采购凭证明细！");
        purVoucher = invoke("voucher.create", MapUtil.mapped(purVoucher));

        changeFrostQty(purVoucher, "服务方案生成，经销带安采购凭证");

        invoke("invoice.create", createInvoiceRequest(purVoucher,order));
        return purVoucher;
    }


    private void createCrossSaleVoucher(Voucher purVoucher, List<MaintenanceOrder> maintenanceOrders){
        MaintenanceOrder workOrder = maintenanceOrders.get(0);
        String platformId = workOrder.getPlatform().getId();    // 平台公司

        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.SALE_ORDER);
        ReflectUtil.copy(purVoucher, voucher, "dept", "company", "clerk", "scene", "customerExpand");

        voucher.setPartner(workOrder.getCompany().getParty().getPartyRoleByType("Customer")); // 门店公司
        Contract contract = contractService.getContract(voucher.getDept(), voucher.getPartner(), "distribution", "customer", "零售工单外协业务");
        voucher.setContract(contract);

        voucher.setInventoryMode(voucher.getContract().getCooperation().getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(voucher.getContract().getCooperation().getAccountingMethod());  // 核算方式

        voucher.setSource(purVoucher.getId());
        voucher.setSourceBusinessType(Voucher.class.getSimpleName());
        voucher.setOrigin(workOrder.getServicePlanId());
        voucher.setOriginBusinessType(ServicePlan.class.getSimpleName());

        voucher.setVoucherItems(
                maintenanceOrders.stream().map(item -> {
                    VoucherItem voucherItem = new VoucherItem();
                    voucherItem.setProduct(item.getProduct());
                    voucherItem.setUom(item.getUom());
                    voucherItem.setProductQty(item.getSaleQty());
                    voucherItem.setOwner(purVoucher.getCompany());

                    voucherItem.setOriginItemId(item.getServicePlanItem().getId());
                    voucherItem.setSourceItemId(item.getId());

                    voucherItem.setDiscount(0d);
                    voucherItem.setTax(voucherItem.getProduct().getTax());
                    voucherItem.setSupplier(purVoucher.getPartner());

                    // 采购价格取带安成本单价
                    if ("1001".equals(platformId)) {
                        voucherItem.setPriceUnit(item.getPriceCostUnitInTax());
                    } else if ("1007".equals(platformId)) {
                        voucherItem.setPriceUnit(item.getPlatformPriceCosInTax());
                    }

                    return voucherItem;
                }).collect(Collectors.toSet()));

        // 添加采购凭证批次以及供应商信息
        voucher.getVoucherItems().forEach(item -> {
            purVoucher.getVoucherItems().forEach(purchaseVoucherItem -> {

                VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(purchaseVoucherItem).stream()
                        .findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));

                if (item.getProduct().getId().equals(voucherInventory.getProduct().getId())) {
                    item.setInventoryBatch(voucherInventory.getInventoryBatch());
                    item.setSupplier(purchaseVoucherItem.getSupplier());
                }
            });
        });

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));

        // 增加与基地账单
        invoke("invoice.create", createInvoiceRequest(voucher,workOrder));
    }

    /**
     * 服务方案的来源渠道为富登时，追加第三方单号与时间字段
     * @param voucher
     * @param order
     * @return
     */
    private Map createInvoiceRequest(Object voucher,MaintenanceOrder order){
        Map invoiceRequest = MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher)));
        ServicePlan servicePlan = SpringManager.getBean(ServicePlanRepository.class).findOne(order.getServicePlanId());
        // 若服务方案来源渠道为富登则拼接入参
        if (Objects.isNull(servicePlan) || !"110".equals(servicePlan.getChannel().getId())) return invoiceRequest;
        invoiceRequest.put("thirdTime",order.getFactoryFittingsTime());
        invoiceRequest.put("thirdId",servicePlan.getSupplierRef());
        return invoiceRequest;
    }

}
